package stone926.mods.more_enchantments.mixins;

import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.item.EnchantedBookItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.enchantments.creative.AbstractCreativeOnlyEnchantment;
import stone926.mods.more_enchantments.enchantments.legendary.AbstractLegendaryEnchantment;
import stone926.mods.more_enchantments.enchantments.negative.AbstractNegativeEnchantment;
import stone926.mods.more_enchantments.enchantments.negative.FlimsyEnchantment;
import stone926.mods.more_enchantments.util.EnchantmentUtil;

import java.util.Random;

import static stone926.mods.more_enchantments.MoreEnchantmentsMod.FLIMSY;
import static stone926.mods.more_enchantments.util.EnchantmentUtil.LEGENDARY_ENCHANTMENTS;
import static stone926.mods.more_enchantments.util.EnchantmentUtil.NEGATIVE_ENCHANTMENTS;

@Mixin(ItemStack.class)
public abstract class ItemStackMixin {

  @Shadow
  public abstract Item getItem();

  @Shadow
  public abstract NbtList getEnchantments();

  @ModifyVariable(method = "damage(ILjava/util/Random;Lnet/minecraft/server/network/ServerPlayerEntity;)Z", at = @At("STORE"), ordinal = 0, argsOnly = true)
  private int damage(int amount) {
    int lvl = EnchantmentHelper.getLevel(FLIMSY, (ItemStack) (Object) this);
    int j = 0;
    for (int k = 0; lvl > 0 && k < amount; ++k) {
      if (FlimsyEnchantment.shouldDamage((ItemStack) (Object) this, lvl, new Random())) {
        ++j;
      }
    }
    return amount + j;
  }

  @Inject(method = "getName", at = @At("TAIL"), cancellable = true)
  private void getName(CallbackInfoReturnable<Text> cir) {
    if (getItem() instanceof EnchantedBookItem book) {
      ItemStack enchantedBookStack = (ItemStack) (Object) this;
      NbtList enchantmentList = EnchantedBookItem.getEnchantmentNbt(enchantedBookStack);

      boolean hasCreativeOnlyEnchantment = false;
      for (AbstractCreativeOnlyEnchantment e : EnchantmentUtil.getCreativeOnlyEnchantmentList()) {
        if (getStoredEnchantmentLevel(enchantmentList, e) > 0) hasCreativeOnlyEnchantment = true;
        if (hasCreativeOnlyEnchantment) break;
      }
      if (hasCreativeOnlyEnchantment) {
        cir.setReturnValue(new TranslatableText("item.stone_more_enchantments.enchanted_book.creative_only").formatted(Formatting.AQUA));
        return;
      }

      boolean hasNegativeEnchantment = false;
      for (AbstractNegativeEnchantment e : NEGATIVE_ENCHANTMENTS) {
        if (getStoredEnchantmentLevel(enchantmentList, e) > 0) hasNegativeEnchantment = true;
        if (hasNegativeEnchantment) break;
      }
      if (hasNegativeEnchantment) {
        cir.setReturnValue(new TranslatableText("item.stone_more_enchantments.enchanted_book.negative").formatted(Formatting.DARK_RED));
        return;
      }

      boolean hasLegendaryEnchantment = false;
      for (AbstractLegendaryEnchantment e : LEGENDARY_ENCHANTMENTS) {
        if (getStoredEnchantmentLevel(enchantmentList, e) > 0) hasLegendaryEnchantment = true;
        if (hasLegendaryEnchantment) break;
      }
      if (hasLegendaryEnchantment) {
        cir.setReturnValue(new TranslatableText("item.stone_more_enchantments.enchanted_book.legendary").formatted(Formatting.DARK_AQUA));
        return;
      }

    }
  }

  private int getStoredEnchantmentLevel(NbtList nbtList, Enchantment enchantment) {
    Identifier identifier = EnchantmentHelper.getEnchantmentId(enchantment);
    for (int i = 0; i < nbtList.size(); ++i) {
      NbtCompound nbtCompound = nbtList.getCompound(i);
      Identifier identifier2 = EnchantmentHelper.getIdFromNbt(nbtCompound);
      if (identifier2 != null && identifier2.equals(identifier)) {
        return EnchantmentHelper.getLevelFromNbt(nbtCompound);
      }
    }
    return 0;
  }

  @Inject(method = "isDamageable", at = @At("HEAD"), cancellable = true)
  public void isDamageable(CallbackInfoReturnable<Boolean> cir) {
    if (EnchantmentUtil.hasEnchantment(MoreEnchantmentsMod.UNBREAKABLE, (ItemStack) (Object) this)) {
      cir.setReturnValue(false);
    }
  }

//  @Inject(method = "decrement", at = @At("HEAD"), cancellable = true)
//  private void inexhaustible(int amount, CallbackInfo ci) {
//    if (EnchantmentUtil.hasEnchantment(MoreEnchantmentsMod.INEXHAUSTIBLE, (ItemStack) (Object) this)) {
//      ci.cancel();
//    }
//  }

}
